﻿/*
 * DebugStream.cpp
 *
 *  Created on: 2011/05/29
 *      Author: naoki
 */

#include "StdAfx.h"
#include <windows.h>
#undef min
#undef max

#include "NTEngine/NTEngine.h"
#include "NTEngine/Base/DebugStream.h"
#include "NTEngine/Base/OStringStream.h"
#include "NTEngine/Threading/Mutex.h"

namespace NTEngine {
using namespace Threading;

DebugStream cout;

class DebugStream::Impl {
public:
	Impl() {
		m_Mutex = Mutex::create();
	}
	OStringStream m_Buffer;
	Mutex m_Mutex;
};

DebugStream::DebugStream()
: m_Impl( 0 ) {
}

void DebugStream::begin() {
	m_Impl = NEW Impl;
}

void DebugStream::end() {
	SAFE_DELETE( m_Impl );
}

DebugStream& DebugStream::operator<<( char a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<(unsigned char a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( short a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( unsigned short a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( int a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( unsigned a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( float a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( double a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( const string& a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( const char* a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( char* a ) {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << a;
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::operator<<( const OStringStream& a ) {
	if ( a.size() > 0 ) {
		Array<char> s;
		a.get( &s );
		m_Impl->m_Mutex.lock();
		m_Impl->m_Buffer << &s[ 0 ];
		m_Impl->m_Mutex.unlock();
	}
	return *this;
}

DebugStream& DebugStream::endl() {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer << '\n';
	Array<char> a;
	m_Impl->m_Buffer.get( &a );
	OutputDebugStringA( &a[ 0 ] );
	m_Impl->m_Buffer.clear();
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::hex() {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer.hex();
	m_Impl->m_Mutex.unlock();
	return *this;
}

DebugStream& DebugStream::dec() {
	m_Impl->m_Mutex.lock();
	m_Impl->m_Buffer.dec();
	m_Impl->m_Mutex.unlock();
	return *this;
}

int DebugStream::precision( int a ) {
	m_Impl->m_Mutex.lock();
	int r = m_Impl->m_Buffer.precision( a );
	m_Impl->m_Mutex.unlock();
	return r;
}

DebugStream& DebugStream::operator<<( DebugStream& ( *f )( DebugStream& ) ) {
	return ( *f )( *this );
}

DebugStream& endl( DebugStream& a ) {
	return a.endl();
}

DebugStream& hex( DebugStream& a ) {
	return a.hex();
}

DebugStream& dec( DebugStream& a ) {
	return a.dec();
}

} // namespace NTEngine
// EOF